﻿using System;
using System.ServiceModel;
using System.Xml;
using System.Collections.Generic;
using System.Data;
using System.Text;
using SdmxMl.Common;
using SdmxMl.Structure;
using SdmxMl.Registry;
using SdmxMl.Manager;
using SdmxMl.SoapArtefactRegistry;
using Ch.Admin.Bfs.Sms.Sdmx.Registry.Rights;
using Ch.Admin.Bfs.Sms.Sdmx.Registry.Proxies;
using Ch.Admin.Bfs.Sms.Sdmx.Common;
using Ch.Admin.Bfs.Sms.Sdmx.Utils;


namespace SdmxMl.Multiplexor
{
    public class SoapRegProxy
    {
        #region Properties

        /// <summary> NSI user ID in SMS system</summary>
        public string UserId { get; private set; }
        public string LastError { get; private set; }

        /// <summary>Current state of connexion</summary>
        public RepositoryState State { get; set; }

        public bool UserIsAdmin { get; set; }
        public string Url { get { return _url; } }

        // Version of Web service used
        public double Version { get; set; }

        public bool BackupAutomatic { get; set; }

        #endregion


        #region Internal Members

        public ISecuredArtefactRegistry artefactRegistry { get; private set; }
        public WcfAdministrationProxy administrationProxy { get; private set; }
        public WcfNotificationsProxy notificationProxy { get; private set; }

        private SoapArtefactRegistry.IWcfArtefactRegistryService smsProxy;
        private string VS;
        private string _url;

        #endregion // Internal Members

        #region C'tor

        // Constructor
        public SoapRegProxy(string url, string vs, string userId)
        {
            LastError = string.Empty;
            string[] arr = url.Split('/');
            string RootWebSiteUrl = url.Substring(0, url.Length - arr[arr.Length - 1].Length);
            //string artefactRegistryUrl = url.Substring(0, url.Length - arr[arr.Length-1].Length) + artefactRegistryService;
            try
            {
                UserId = userId.ToUpper();
                VS = vs;
                _url = url;

                Test();

                artefactRegistry = GetArtefactRegistry(RootWebSiteUrl);
                administrationProxy = GetAdministrationProxy(RootWebSiteUrl);
                notificationProxy = GetNotificationProxy(RootWebSiteUrl);
            }
            catch
            {
                State = RepositoryState.OnError;
            }
        }


        private ISecuredArtefactRegistry GetArtefactRegistry(string RootWebSiteUrl)
        {
            string artefactRegistryUrl = RootWebSiteUrl + "WcfArtefactRegistryService.svc";

            // Init the end point of the proxy (i.e., the url of the server to which is connect the proxy)
            EndpointAddress address = new EndpointAddress(artefactRegistryUrl);

            // Init the binding of the proxy (i.e., how the proxy is connected to the server)
            BasicHttpBinding binding = new BasicHttpBinding();
            binding.MaxBufferPoolSize = 2147483647;
            binding.MaxBufferSize = 2147483647;
            binding.MaxReceivedMessageSize = 2147483647;
            binding.Security.Mode = BasicHttpSecurityMode.TransportCredentialOnly;
            binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Windows;

            return new WcfArtefactRegistryProxy(address, binding, "CH1");

        }

        private WcfAdministrationProxy GetAdministrationProxy(string RootWebSiteUrl)
        {
            string administrationUrl = RootWebSiteUrl + "WcfAdministrationService.svc";

            // Init the end point of the proxy (i.e., the url of the server to which is connect the proxy)
            EndpointAddress address = new EndpointAddress(administrationUrl);

            // Init the binding of the proxy (i.e., how the proxy is connected to the server)
            BasicHttpBinding binding = new BasicHttpBinding();
            binding.SendTimeout = new TimeSpan(3, 0, 0);
            binding.MaxBufferPoolSize = int.MaxValue;
            binding.MaxBufferSize = int.MaxValue;
            binding.MaxReceivedMessageSize = int.MaxValue;
            binding.Security.Mode = BasicHttpSecurityMode.TransportCredentialOnly;
            binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Windows;

            administrationProxy = new WcfAdministrationProxy(address, binding);
            (administrationProxy as WcfAdministrationProxy).Credentials.Windows.ClientCredential = System.Net.CredentialCache.DefaultNetworkCredentials;
            return administrationProxy;
        }

        private WcfNotificationsProxy GetNotificationProxy(string RootWebSiteUrl)
        {
            string administrationUrl = RootWebSiteUrl + "WcfNotificationsService.svc";

            // Init the end point of the proxy (i.e., the url of the server to which is connect the proxy)
            EndpointAddress address = new EndpointAddress(administrationUrl);

            // Init the binding of the proxy (i.e., how the proxy is connected to the server)
            BasicHttpBinding binding = new BasicHttpBinding();
            binding.SendTimeout = new TimeSpan(3, 0, 0);
            binding.MaxBufferPoolSize = int.MaxValue;
            binding.MaxBufferSize = int.MaxValue;
            binding.MaxReceivedMessageSize = int.MaxValue;
            binding.Security.Mode = BasicHttpSecurityMode.TransportCredentialOnly;
            binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Windows;

            return new WcfNotificationsProxy(address, binding, "CH1");
        }

        #endregion

        #region Test registry access

        public RepositoryState Test()
        {
            try
            {
                LastError = string.Empty;
                smsProxy = new SoapArtefactRegistry.IWcfArtefactRegistryService();
                smsProxy.Credentials = System.Net.CredentialCache.DefaultCredentials;

                smsProxy.Url = _url;

                //let's do an access and Get version of WS used
                Version = 0;
                StatusMessageType statusMsg = new StatusMessageType(smsProxy.Test());
                if (statusMsg.IsStatusMessage == true)
                {
                    string versionLongue = statusMsg.Message.GetFirst();
                    string parseStringPass = versionLongue.Split(':')[1];
                    string[] parts = parseStringPass.Trim().Split('.');

                    Version = Convert.ToDouble(parts[0] + "." + parts[1]);

                    #region DEC 10.08.2011 : Backup version management
                    BackupAutomatic = false;
                    UserIsAdmin = false;
                    if (Version >= 1.0)
                    {
                        BackupAutomatic = smsProxy.BackupAutomaticEnable();
                        UserIsAdmin = IsAdministrator();
                    }

                    State = RepositoryState.Ok;

                }
                else
                    throw new ApplicationException("Unknown format for answered Test status");


                    #endregion
            }
            catch (Exception ex)
            {
                LastError = ex.Message;
                State = RepositoryState.OnError;
            }
            return State;
        }
        #endregion

        #region Public access to Registry service methods

        public string GetLastVersion(string arType, string fullIdent)
        {
            //      arType = ArTypeTranslate(arType);
            XmlDocument xDoc = null;
            string lastVers = "1.0";
            string[] arr = fullIdent.Split('+');
            if (arr.Length == 3)
                lastVers = arr[2];

            if (State == RepositoryState.Ok && Version >= 1.5)
            {
                StatusMessageType statusMsg = new StatusMessageType();
                try
                {
                    XmlElement el = smsProxy.GetVersionEvolution(arType, fullIdent);
                    statusMsg = new StatusMessageType(el);
                    if (statusMsg.IsStatusMessage == false)
                    {
                        xDoc = new XmlDocument();
                        xDoc.LoadXml(el.OuterXml);
                        // we get a codelist with all versions as code
                        SmManager sm = new SmManager();
                        sm.LoadSdmxDocument(null, true, xDoc);
                        CodeListType clt = sm.GetArtefact(new ArtefactRefTyped(SdmxArtefactType.CodeLists, "NSI+CL_LAST_UPDATE+1.0")) as CodeListType;
                        if (clt != null && clt.CodeList.Count > 0)
                        {
                            double v = 0.0;
                            foreach (CodeType c in clt.CodeList)
                            {
                                double vc = double.Parse(c.Id.Replace("_", "."));
                                if (vc > v)
                                    v = vc;
                            }
                            lastVers = v.ToString("0.0");
                        }
                    }
                }
                catch (Exception ex)
                {
                    StringBuilder sb = new StringBuilder(256);
                    sb.Append("Unable to fetch metadata from registry.").Append(Environment.NewLine);
                    sb.Append("Type: ").Append(arType).Append(Environment.NewLine);
                    sb.Append("Full Id: ").Append(fullIdent).Append(Environment.NewLine);
                    sb.Append("Reason: ").Append(ex.Message);

                    State = RepositoryState.OnError;

                    throw new ApplicationException(sb.ToString(), ex);
                }
                if (statusMsg.IsStatusMessage)
                {
                    throw new ApplicationException("Unable to fetch metadata from registry." + Environment.NewLine + "Reason: " + statusMsg.Message);
                }
            }

            return lastVers;
        }

        public XmlDocument GetArtefact(string arType, string fullIdent)
        {
            //         arType = ArTypeTranslate(arType);
            XmlDocument xDoc = null;

            if (State == RepositoryState.Ok)
            {
                StatusMessageType statusMsg = new StatusMessageType();
                try
                {
                    XmlElement el = smsProxy.GetArtefactOS(UserId, VS, arType, fullIdent);
                    statusMsg = new StatusMessageType(el);
                    if (statusMsg.IsStatusMessage == false)
                    {
                        xDoc = new XmlDocument();
                        xDoc.LoadXml(el.OuterXml);
                        // xDoc.Save("c:\\doc\\truc.xml");
                    }
                }
                catch (Exception ex)
                {
                    StringBuilder sb = new StringBuilder(256);
                    sb.Append("Unable to fetch metadata from registry.").Append(Environment.NewLine);
                    sb.Append("Type: ").Append(arType).Append(Environment.NewLine);
                    sb.Append("Full Id: ").Append(fullIdent).Append(Environment.NewLine);
                    sb.Append("Reason: ").Append(ex.Message);

                    State = RepositoryState.OnError;

                    throw new ApplicationException(sb.ToString(), ex);
                }
                if (statusMsg.IsStatusMessage)
                {
                    throw new ApplicationException("Unable to fetch metadata from registry." + Environment.NewLine + "Reason: " + statusMsg.Message);
                }
            }

            return xDoc;
        }

        public bool ExistArtefact(string arType, string fullIdent)
        {
            //   arType = ArTypeTranslate(arType);
            bool exist = false;

            if (State == RepositoryState.Ok)
            {
                StatusMessageType statusMsg = new StatusMessageType();
                try
                {
                    XmlElement el = smsProxy.ExistArtefact(arType, fullIdent);
                    statusMsg = new StatusMessageType(el);
                }
                catch (Exception ex)
                {
                    StringBuilder sb = new StringBuilder(256);
                    sb.Append("Unable to check metadata in registry.").Append(Environment.NewLine);
                    sb.Append("Type: ").Append(arType).Append(Environment.NewLine);
                    sb.Append("Full Id: ").Append(fullIdent).Append(Environment.NewLine);
                    sb.Append("Reason: ").Append(ex.Message);

                    State = RepositoryState.OnError;

                    throw new ApplicationException(sb.ToString(), ex);
                }

                if (statusMsg.Status == StatusType.Failure)
                {
                    throw new ApplicationException("Unable to check Artefact existence. Reason: " + statusMsg.Message);
                }
                else
                    exist = statusMsg.Message.GetFirst() == "True"; // sucess if exist, warning if not existing
            }


            return exist;
        }

        public void DeleteArtefact(string arType, string fullIdent)
        {
            //    arType = ArTypeTranslate(arType);
            if (State == RepositoryState.Ok)
            {
                StatusMessageType statusMsg = new StatusMessageType();
                try
                {
                    // For new Registry checkout needed 
                    CheckOut(arType, fullIdent);

                    XmlElement el = smsProxy.DeleteArtefact(UserId, VS, arType, fullIdent);
                    statusMsg = new StatusMessageType(el);
                }
                catch (Exception ex)
                {
                    StringBuilder sb = new StringBuilder(256);
                    sb.Append("Unable to delete metadata in registry.").Append(Environment.NewLine);
                    sb.Append("Type: ").Append(arType).Append(Environment.NewLine);
                    sb.Append("Full Id: ").Append(fullIdent).Append(Environment.NewLine);
                    sb.Append("Reason: ").Append(ex.Message);

                    State = RepositoryState.OnError;

                    throw new ApplicationException(sb.ToString(), ex);
                }

                if (statusMsg.Status == StatusType.Failure)
                {
                    throw new ApplicationException("Unable to delete Artefact. Reason: " + statusMsg.Message);
                }
            }
        }

        public void SetDisseminationStatus(string artType, string fullId, string diffusionCd)
        {
            //     artType = ArTypeTranslate(artType);
            if (State == RepositoryState.Ok)
            {
                StatusMessageType statusMsg = new StatusMessageType();
                try
                {
                    // For new Registry checkout needed 
                    CheckOut(artType, fullId);

                    XmlElement el = smsProxy.SetDisseminationStatus(UserId, VS, artType, fullId, diffusionCd);
                    statusMsg = new StatusMessageType(el);

                    // For new Registry checkIn needed 
                    UndoCheckOut(artType, fullId);


                }
                catch (Exception ex)
                {
                    StringBuilder sb = new StringBuilder(256);
                    sb.Append("Unable to set diffusion status to registry.").Append(Environment.NewLine);
                    sb.Append("Type: ").Append(artType).Append(Environment.NewLine);
                    sb.Append("Full Id: ").Append(fullId).Append(Environment.NewLine);
                    sb.Append("Reason: ").Append(ex.Message);

                    State = RepositoryState.OnError;

                    throw new ApplicationException(sb.ToString(), ex);
                }

                if (statusMsg.Status == StatusType.Failure)
                {
                    throw new ApplicationException("Unable to set diffusion status to registry. Reason: " + statusMsg.Message);
                }
            }
        }

        #region DEC update 17.08.2011 : Implement method to bacup artefact before submission
        public void SubmitArtefactBackup(string arType, string fullIdent, XmlElement element)
        {
            //     arType = ArTypeTranslate(arType);
            if (State == RepositoryState.Ok)
            {
                StatusMessageType statusMsg = new StatusMessageType();
                try
                {
                    XmlElement el = smsProxy.SubmitArtefactBackup(UserId, VS, arType, fullIdent, element);
                    statusMsg = new StatusMessageType(el);
                }
                catch (Exception ex)
                {
                    StringBuilder sb = new StringBuilder(256);
                    sb.Append("Unable to submit metadata to registry.").Append(Environment.NewLine);
                    sb.Append("Type: ").Append(arType).Append(Environment.NewLine);
                    sb.Append("Full Id: ").Append(fullIdent).Append(Environment.NewLine);
                    sb.Append("Reason: ").Append(ex.Message);

                    State = RepositoryState.OnError;

                    throw new ApplicationException(sb.ToString(), ex);
                }

                if (statusMsg.Status == StatusType.Failure)
                {
                    throw new ApplicationException("Unable to submit artefact. Reason: " + statusMsg.Message);
                }
            }
        }
        #endregion

        public void SubmitArtefact(string arType, string fullIdent, XmlElement element)
        {
            //     arType = ArTypeTranslate(arType);
            if (State == RepositoryState.Ok)
            {
                StatusMessageType statusMsg = new StatusMessageType();
                try
                {
                    XmlElement el = smsProxy.SubmitArtefact(UserId, VS, arType, fullIdent, element);
                    statusMsg = new StatusMessageType(el);
                }
                catch (Exception ex)
                {
                    StringBuilder sb = new StringBuilder(256);
                    sb.Append("Unable to submit metadata to registry.").Append(Environment.NewLine);
                    sb.Append("Type: ").Append(arType).Append(Environment.NewLine);
                    sb.Append("Full Id: ").Append(fullIdent).Append(Environment.NewLine);
                    sb.Append("Reason: ").Append(ex.Message);

                    State = RepositoryState.OnError;

                    throw new ApplicationException(sb.ToString(), ex);
                }

                if (statusMsg.Status == StatusType.Failure)
                {
                    throw new ApplicationException("Unable to submit artefact. Reason: " + statusMsg.Message);
                }
            }
        }

        public void CheckOut(string arType, string fullIdent)
        {
            //     arType = ArTypeTranslate(arType);
            if (State == RepositoryState.Ok)
            {
                StatusMessageType statusMsg = new StatusMessageType();
                try
                {
                    XmlElement el = smsProxy.CheckOut(UserId, VS, arType, fullIdent);
                    statusMsg = new StatusMessageType(el);
                }
                catch (Exception ex)
                {
                    StringBuilder sb = new StringBuilder(256);
                    sb.Append("Unable to check out artefact in registry.").Append(Environment.NewLine);
                    sb.Append("Type: ").Append(arType).Append(Environment.NewLine);
                    sb.Append("Full Id: ").Append(fullIdent).Append(Environment.NewLine);
                    sb.Append("Reason: ").Append(ex.Message);

                    State = RepositoryState.OnError;

                    throw new ApplicationException(sb.ToString(), ex);
                }

                if (statusMsg.Status == StatusType.Failure)
                {
                    throw new ApplicationException("Unable to lock artefact in registry ! : " + statusMsg.Message);
                }
            }
        }

        public void UndoCheckOut(string arType, string fullIdent)
        {
            //      arType = ArTypeTranslate(arType);
            if (State == RepositoryState.Ok)
            {
                StatusMessageType statusMsg = new StatusMessageType();
                try
                {
                    XmlElement el = smsProxy.UndoCheckOut(UserId, VS, arType, fullIdent);
                    statusMsg = new StatusMessageType(el);
                }
                catch (Exception ex)
                {
                    StringBuilder sb = new StringBuilder(256);
                    sb.Append("Unable to unlock artefact in registry.").Append(Environment.NewLine);
                    sb.Append("Type: ").Append(arType).Append(Environment.NewLine);
                    sb.Append("Full Id: ").Append(fullIdent).Append(Environment.NewLine);
                    sb.Append("Reason: ").Append(ex.Message);

                    State = RepositoryState.OnError;

                    throw new ApplicationException(sb.ToString(), ex);
                }

                if (statusMsg.Status == StatusType.Failure)
                {
                    throw new ApplicationException("Unable to check out artefact in registry ! : " + statusMsg.Message);
                }

            }
        }

        /// <summary>Retrieves information list of artefact for specified type </summary>
        /// <param name="arType">Artefact type</param>
        /// <returns>A dataset holding the information table</returns>
        public System.Data.DataSet DirInfo(string arType)
        {
            //       arType = ArTypeTranslate(arType);
            System.Data.DataSet ds = new System.Data.DataSet();
            if (State == RepositoryState.Ok)
            {
                try
                {
                    ds = smsProxy.DirInfo(arType);
                    //   ds.WriteXml("c:\\doc\\dirinfo.xml");
                }
                catch (Exception ex)
                {
                    StringBuilder sb = new StringBuilder(256);
                    sb.Append("Unable to obtain metadata list from registry.").Append(Environment.NewLine);
                    sb.Append("Type: ").Append(arType).Append(Environment.NewLine);
                    sb.Append("Reason: ").Append(ex.Message);

                    State = RepositoryState.OnError;

                    throw new ApplicationException(sb.ToString(), ex);
                }
            }

            //foreach (DataRow row in ds.Tables[0].Rows)
            //    if (row["IF"].ToString().ToLower() == "true")
            //        ds.Tables[0].TableName = "XX";

            return ds;
        }

        /// <summary>
        ///translate type to defined types in sdmx 2.1 Patterns not supported (START_PATTERN = "\\A"; END_PATTERN = "\\z";
        /// </summary>
        /// <param name="strPatterned"></param>
        /// <returns></returns>
        private string RemoveSearchPattern(string strPatterned)
        {
            string trType = strPatterned.Remove(0, 2);
            return trType.Substring(0, trType.Length - 2);
        }

        /// <summary>Retrieves information list of artefact for specified type </summary>
        /// <param name="arType">Artefact type</param>
        /// <returns>A dataset holding the information table</returns>
        public System.Data.DataSet GetArtefactInfos(string artTypePattern, string agencyPattern, string idPattern, string versionPattern, DateTime start, DateTime end)
        {

            // Patterns not supported (START_PATTERN = "\\A"; END_PATTERN = "\\z";
            string arType = RemoveSearchPattern(artTypePattern).ToLower();
            agencyPattern = RemoveSearchPattern(agencyPattern);
            idPattern = RemoveSearchPattern(idPattern);

            //translate type to defined types in sdmx 2.1 
            string trType = ConvertOldTypeToNewType(arType);
            versionPattern = versionPattern.Replace('*', '%');

            // remove 
            System.Data.DataSet ds = new System.Data.DataSet();
            if (State == RepositoryState.Ok)
            {
                try
                {
                    ds = smsProxy.GetArtefactInfos(trType, agencyPattern, idPattern, versionPattern, start, end);
                }
                catch (Exception ex)
                {
                    StringBuilder sb = new StringBuilder(256);
                    sb.Append("Unable to obtain metadata list from registry.").Append(Environment.NewLine);
                    sb.Append("Params: ").Append(artTypePattern).Append(", ").Append(agencyPattern).Append(", ").Append(idPattern).Append(", ").Append(versionPattern).Append(", ").Append(start.ToString()).Append(", ").Append(end.ToString()).Append(Environment.NewLine);
                    sb.Append("Reason: ").Append(ex.Message);

                    State = RepositoryState.OnError;

                    throw new ApplicationException(sb.ToString(), ex);
                }
            }

            return ds;
        }

        #region DEC 10.08.2011 : Add information on backup version

        /// <summary>Determines if backup info exists</summary>
        /// <param name="ar">Artefact type</param> <param name="fullId">Artefact Key</param>
        /// <returns>True if exists</returns>
        public bool IsBackupExist(string ar, string fullId)
        {
            //        ar = ArTypeTranslate(ar);
            bool bReturn = false;
            DataSet ds = GetBackupList(ar, fullId);

            if (ds != null && ds.Tables.Count == 1 && ds.Tables[0].Rows.Count > 0)
                bReturn = true;

            return (bReturn);
        }

        /// <summary> Get list of backup of specified artefact</summary>
        /// <param name="ar">Artefact type</param> <param name="fullId">Artefact Key</param>
        /// <returns>A dataset holding backup list information</returns>
        public DataSet GetBackupList(string ar, string fullId)
        {
            DataSet dsReturn = new DataSet();
            //    ar = ArTypeTranslate(ar);

            if (State == RepositoryState.Ok)
            {
                try
                {
                    dsReturn = smsProxy.GetArtefactBackupList(ar, fullId);
                }
                catch (Exception ex)
                {
                    StringBuilder sb = new StringBuilder(256);
                    sb.Append("Unable to obtain metadata list from registry.").Append(Environment.NewLine);
                    sb.Append("Type: ").Append(ar).Append(Environment.NewLine);
                    sb.Append("Reason: ").Append(ex.Message);

                    State = RepositoryState.OnError;

                    throw new ApplicationException(sb.ToString(), ex);
                }
            }

            return (dsReturn);
        }

        /// <summary> Retrieve a backuped Artefact document </summary>
        /// <param name="ar">Artefact type</param> <param name="fullId">Artefact Key</param>
        /// <param name="versionNumber">Backup number</param>
        /// <returns></returns>
        public XmlDocument GetArtefactBackup(string ar, string fullId, string versionNumber)
        {
            //    ar = ArTypeTranslate(ar);

            XmlDocument xDoc = null;

            if (State == RepositoryState.Ok)
            {
                StatusMessageType statusMsg = new StatusMessageType();
                try
                {
                    XmlElement el = smsProxy.GetArtefactBackup(UserId,
                        VS,
                        ar,
                        fullId,
                        versionNumber);

                    statusMsg = new StatusMessageType(el);
                    if (statusMsg.IsStatusMessage == false)
                    {
                        xDoc = new XmlDocument();
                        xDoc.LoadXml(el.OuterXml);
                    }
                }
                catch (Exception ex)
                {
                    StringBuilder sb = new StringBuilder(256);
                    sb.Append("Unable to fetch metadata from registry.").Append(Environment.NewLine);
                    sb.Append("Type: ").Append(ar).Append(Environment.NewLine);
                    sb.Append("Full Id: ").Append(fullId).Append(Environment.NewLine);
                    sb.Append("Reason: ").Append(ex.Message);

                    State = RepositoryState.OnError;

                    throw new ApplicationException(sb.ToString(), ex);
                }
                if (statusMsg.IsStatusMessage)
                {
                    throw new ApplicationException("Unable to fetch metadata from registry." + Environment.NewLine + "Reason: " + statusMsg.Message);
                }
            }

            return xDoc;
        }
        #endregion

        /// <summary>
        /// Is window used a repository administrator
        /// </summary>
        /// <returns>True id administrator</returns>
        public bool IsAdministrator() { return IsAdministrator(UserId); }
        public bool IsAdministrator(string uid)
        {
            bool isAdmin = false;
            if (State == RepositoryState.Ok)
            {
                StatusMessageType statusMsg = new StatusMessageType();
                try
                {
                    XmlElement el = smsProxy.IsAdministrator(uid, VS);
                    statusMsg = new StatusMessageType(el);
                }
                catch (Exception ex)
                {
                    StringBuilder sb = new StringBuilder(256);
                    sb.Append("Unable to get information about administrative user").Append(Environment.NewLine);
                    sb.Append("Reason: ").Append(ex.Message);

                    State = RepositoryState.OnError;

                    throw new ApplicationException(sb.ToString(), ex);
                }

                if (statusMsg.Status == StatusType.Failure)
                {
                    throw new ApplicationException("Unable to get information about administrative user. Reason: " + statusMsg.Message);
                }
                else
                    isAdmin = statusMsg.Status == StatusType.Success && statusMsg.Message.GetFirst().ToLower() == "true";
            }


            return isAdmin;
        }

        public bool IsOwner(string uid, string fullId)
        {
            bool isOwner = false;

            if (State == RepositoryState.Ok && Version >= 1.6)
            {
                StatusMessageType statusMsg = new StatusMessageType();
                try
                {
                    XmlElement el = smsProxy.IsOwner(uid, VS, fullId);
                    statusMsg = new StatusMessageType(el);
                }
                catch (Exception ex)
                {
                    StringBuilder sb = new StringBuilder(256);
                    sb.Append("Unable to get information about ownership").Append(Environment.NewLine);
                    sb.Append("Reason: ").Append(ex.Message);

                    State = RepositoryState.OnError;

                    throw new ApplicationException(sb.ToString(), ex);
                }

                if (statusMsg.Status == StatusType.Failure)
                {
                    throw new ApplicationException("Unable to get information about ownership. Reason: " + statusMsg.Message);
                }
                else
                    isOwner = statusMsg.Status == StatusType.Success && statusMsg.Message.GetFirst().ToLower() == "is owner";
            }


            return isOwner;
        }


        #endregion

        private string ArTypeTranslate(string arType)
        {
            return ConvertOldTypeToNewType(arType);
        }

        public static string ConvertOldTypeToNewType(string type)
        {
            string result = type;
            result = (result == "OrganisationSchemes") ? ArtefactType.AgencyScheme.GetDescription() : result;
            result = (result == "Dataflows") ? ArtefactType.DataFlowDefinition.GetDescription() : result;
            result = (result == "Metadataflows") ? ArtefactType.MetadataFlowDefinition.GetDescription() : result;
            result = (result == "CategorySchemes") ? ArtefactType.CategoryScheme.GetDescription() : result;
            result = (result == "Categorisations") ? ArtefactType.Categorisation.GetDescription() : result;
            result = (result == "CodeLists") ? ArtefactType.Codelist.GetDescription() : result;
            result = (result == "HierarchicalCodelists") ? ArtefactType.HierarchicalCodelist.GetDescription() : result;
            result = (result == "Concepts") ? ArtefactType.ConceptScheme.GetDescription() : result;
            result = (result == "StructureSets") ? ArtefactType.StructureSet.GetDescription() : result;
            result = (result == "ReportingTaxonomies") ? ArtefactType.ReportingTaxonomy.GetDescription() : result;
            result = (result == "Processes") ? ArtefactType.Process.GetDescription() : result;
            result = (result == "MetadataSet") ? ArtefactType.MetadataSet.GetDescription() : result;
            result = (result == "MetadataStructureDefinitions") ? ArtefactType.MetadataStructureDefinition.GetDescription() : result;
            result = (result == "KeyFamilies") ? ArtefactType.DataStructureDefinition.GetDescription() : result;

            return result;
        }

        private string ConvertNewTypeToOldType(string newType)
        {
            string result = newType;
            result = (result == ArtefactType.AgencyScheme.GetDescription()) ? "OrganisationSchemes" : result;
            result = (result == ArtefactType.DataFlowDefinition.GetDescription()) ? "Dataflows" : result;
            result = (result == ArtefactType.MetadataFlowDefinition.GetDescription()) ? "Metadataflows" : result;
            result = (result == ArtefactType.CategoryScheme.GetDescription()) ? "CategorySchemes" : result;
            result = (result == ArtefactType.Categorisation.GetDescription()) ? "Categorisations" : result;
            result = (result == ArtefactType.Codelist.GetDescription()) ? "CodeLists" : result;
            result = (result == ArtefactType.HierarchicalCodelist.GetDescription()) ? "HierarchicalCodelists" : result;
            result = (result == ArtefactType.ConceptScheme.GetDescription()) ? "Concepts" : result;
            result = (result == ArtefactType.StructureSet.GetDescription()) ? "StructureSets" : result;
            result = (result == ArtefactType.ReportingTaxonomy.GetDescription()) ? "ReportingTaxonomies" : result;
            result = (result == ArtefactType.Process.GetDescription()) ? "Processes" : result;
            result = (result == ArtefactType.MetadataSet.GetDescription()) ? "MetadataSet" : result;
            result = (result == ArtefactType.MetadataStructureDefinition.GetDescription()) ? "MetadataStructureDefinitions" : result;
            result = (result == ArtefactType.DataStructureDefinition.GetDescription()) ? "KeyFamilies" : result;
            return result;
        }


        /// <summary> Update text part of the specified finalized maintenable artefact </summary>
        /// <param name="arType">Type of artefact</param>
        /// <param name="fullIdent">AgencyId + Id + version</param>
        /// <param name="xDoc">the maintenable artefact sdmx document</param>
        public void UpdateFinalizedArtefact(string arType, string fullIdent, XmlDocument xDoc)
        {
            StatusMessageType statusMsg = new StatusMessageType();
            try
            {
                XmlElement el = smsProxy.UpdateFinalized(UserId, VS, arType, fullIdent, xDoc.DocumentElement);
                statusMsg = new StatusMessageType(el);
            }
            catch (Exception ex)
            {
                StringBuilder sb = new StringBuilder(256);
                sb.Append("Unable to Update text of artefact in registry.").Append(Environment.NewLine);
                sb.Append("Type: ").Append(arType).Append(Environment.NewLine);
                sb.Append("Full Id: ").Append(fullIdent).Append(Environment.NewLine);
                sb.Append("Reason: ").Append(ex.Message);

                throw new ApplicationException(sb.ToString(), ex);
            }

            if (statusMsg.Status == StatusType.Failure)
            {
                throw new ApplicationException("Unable to Update text of artefact in registry. Reason: " + statusMsg.Message);
            }

        }

        public void UpdateOwner(string artType, string fullId, string ownerId)
        {
            try
            {
                ArtefactType type = ArtefactTypeUtil.GetArtefactType(ConvertOldTypeToNewType(artType));
                if (!(type == ArtefactType.DataSet) || (type == ArtefactType.MetadataSet))
                {
                    // For new Registry checkout needed 
                    CheckOut(artType, fullId);

                    MaintainableArtefactReference reference = new MaintainableArtefactReference(type, fullId);
                    artefactRegistry.UpdateOwner(reference, ownerId);

                    // For new Registry checkIn needed 
                    UndoCheckOut(artType, fullId);
                }
            }
            catch (Exception ex)
            {
                StringBuilder sb = new StringBuilder(256);
                sb.Append("Unable to set Owner to registry.").Append(Environment.NewLine);
                sb.Append("Type: ").Append(artType).Append(Environment.NewLine);
                sb.Append("Full Id: ").Append(fullId).Append(Environment.NewLine);
                sb.Append("Reason: ").Append(ex.Message);

                throw new ApplicationException(sb.ToString(), ex);
            }

        }

        /// <summary> Obtains list of Owner group associated to user </summary>
        /// <param name="ownerId">Window user id</param>
        /// <param name="isAdministrator">True if user has administration right in Registry</param>
        /// <returns>List of owner group where user is part of, full list for administrator</returns>
        public List<string> UserOwnerList(string ownerId, bool isAdministrator)
        {
            OwnerHelper h = new OwnerHelper(artefactRegistry);
            return h.GetUserUnits(isAdministrator ? null : UserId);
        }




    }
}
